<!DOCTYPE html>
<html lang="zh-CN">
<head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/tree/4.1.5'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://cdn.jsdelivr.net'>
  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <!-- 页面元数据 -->
  
  <title>Pointers on C - Learn - Schenk - Blog</title>
  
    <meta name="keywords" content="c">
  

  
    <meta name="description" content="C学习记录">
  

  <!-- feed -->
  

  <!-- import meta -->
  

  <!-- link -->
  
    <link rel="shortcut icon" type='image/x-icon' href="https://cdn.jsdelivr.net/gh/Schenk75/Source/logos/steroids.svg">
  

  <!-- import link -->
  

  
    
<link rel="stylesheet" href="/css/first.css">

  

  
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  

  <script id="loadcss"></script>

</head>

<body>
  

<header id="l_header" class="l_header auto shadow blur floatable show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://cdn.jsdelivr.net/gh/Schenk75/Source@latest/logos/taiga.svg'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

  <div id="l_body">
    <div id="l_cover">
  
    
        <div id="full" class='cover-wrapper post dock' style="display: none;">
          
            <div class='cover-bg lazyload placeholder' data-bg="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/interstellar.jpg"></div>
          
          <div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Schenk - Blog</p>
    
    
      <p class="subtitle">SJTUer | Cuber</p>
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/categories/"
              
              
              id="categories">
              <i class='fas fa-folder-open fa-fw'></i><p>分类</p>
            </a>
          
            <a href="/tags/"
              
              
              id="tags">
              <i class='fas fa-tags fa-fw'></i><p>标签</p>
            </a>
          
            <a href="/archives/"
              
              
              id="archives">
              <i class='fas fa-archive fa-fw'></i><p>归档</p>
            </a>
          
            <a href="/friends/"
              
              
              id="friends">
              <i class='fas fa-link fa-fw'></i><p>友链</p>
            </a>
          
            <a href="/about/"
              
              
              id="about">
              <i class='fas fa-info-circle fa-fw'></i><p>关于</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

          <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
        </div>
    
  
  </div>

    <div id='safearea'>
      <div class='body-wrapper' id="pjax-container">
        

<div class='l_main'>
  <article class="article post white-box reveal md shadow floatable article-type-post" id="post" itemscope itemprop="blogPost">
  


  
  <div class="article-meta" id="top">
    
    
    
      <h1 class="title">
        Pointers on C - Learn
      </h1>
      <div class='new-meta-box'>
        
          
            
<div class='new-meta-item author'>
  <a class='author' href="/" rel="nofollow">
    <img no-lazy src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/avatar.jpg">
    <p>Schenk</p>
  </a>
</div>

          
        
          
            
  <div class='new-meta-item category'>
    <a class='notlink'>
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <a class="category-link" href="/categories/C/">C</a><span class="sep"></span><a class="category-link" href="/categories/Notes/">Notes</a>
    </a>
  </div>


          
        
          
            <div class="new-meta-item date" itemprop="dateUpdated" datetime="2022-06-20T22:10:09+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2022年6月20日</p>
  </a>
</div>

          
        
          
            
  <div class="new-meta-item wordcount">
    <a class='notlink'>
      <i class="fas fa-keyboard fa-fw" aria-hidden="true"></i>
      <p>字数：7.8k字</p>
    </a>
  </div>
  <div class="new-meta-item readtime">
    <a class='notlink'>
      <i class="fas fa-hourglass-half fa-fw" aria-hidden="true"></i>
      <p>时长：31分钟</p>
    </a>
  </div>


          
        
          
            
  <div class="new-meta-item browse leancloud">
    <a class='notlink'>
      
      <div id="lc-pv" data-title="Pointers on C - Learn" data-path="/2020/11/11/learning-notes/C%E5%92%8C%E6%8C%87%E9%92%88notes/">
        <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
        <span id='number'><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
        次浏览
      </div>
    </a>
  </div>


          
        
      </div>
    
  </div>


  
  <h2 id="Ch2-基本概念">Ch2 基本概念</h2>
<h3 id="2-1-环境">2.1 环境</h3>
<h4 id="2-1-1-翻译环境">2.1.1 翻译环境</h4>
<ul>
<li>
<p>翻译过程：各源文件通过<code>编译过程</code>分别转为<strong>目标代码</strong> -&gt; 各目标代码文件由<strong>链接器</strong>捆绑为单一完整的可执行程序</p>
</li>
<li>
<p>编译过程：预处理器处理 -&gt; 源代码经过<strong>解析</strong>判断语句的意思，从而生成目标代码 -&gt; 优化器对目标代码进一步处理</p>
</li>
</ul>
<h4 id="2-1-4-执行环境">2.1.4 执行环境</h4>
<ul>
<li>
<p>程序执行过程：程序载入内存 -&gt; 启动程序调用main函数 -&gt; 程序的终止</p>
</li>
<li>
<p>程序运行过程中使用一个运行时的<strong>堆栈</strong>，用于存储函数的局部变量和返回地址；同时，程序也可以使用<strong>静态内存</strong>，其中的值在程序整个执行过程都会保留</p>
</li>
</ul>
<h3 id="2-2-词法规则">2.2 词法规则</h3>
<h4 id="2-2-1-字符">2.2.1 字符</h4>
<ul>
<li>
<p>\ddd：三个八进制数字表示的字符</p>
</li>
<li>
<p>\xddd：三个十六进制数字表示的字符</p>
</li>
</ul>
<h4 id="2-2-2-注释">2.2.2 注释</h4>
<ul>
<li>
<p>//：单行注释</p>
</li>
<li>
<p>/*     */：多行注释</p>
</li>
</ul>
<h3 id="TIPS">TIPS:</h3>
<ul>
<li>有的程序从标准输入读取数据，读到EOF停止，在终端输入时Ctrl+D即为输入EOF</li>
</ul>
<h2 id="Ch3-数据">Ch3 数据</h2>
<h3 id="3-1-基本数据类型">3.1 基本数据类型</h3>
<h4 id="3-1-1-整型">3.1.1 整型</h4>
<p>变量的最小范围</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>最小范围</th>
</tr>
</thead>
<tbody>
<tr>
<td>char</td>
<td>0 ~ 2<sup>7</sup>-1</td>
</tr>
<tr>
<td>signed char</td>
<td>-(2<sup>7</sup>-1) ~ 2<sup>7</sup>-1</td>
</tr>
<tr>
<td>unsigned char</td>
<td>0 ~ 2<sup>8</sup>-1</td>
</tr>
<tr>
<td>short int</td>
<td>-(2<sup>15</sup>-1) ~ 2<sup>15</sup>-1</td>
</tr>
<tr>
<td>unsigned short int</td>
<td>0 ~ 2<sup>16</sup>-1</td>
</tr>
<tr>
<td>int</td>
<td>-(2<sup>15</sup>-1) ~ 2<sup>15</sup>-1</td>
</tr>
<tr>
<td>unsigned int</td>
<td>0 ~ 2<sup>16</sup>-1</td>
</tr>
<tr>
<td>long int</td>
<td>-(2<sup>31</sup>-1) ~ 2<sup>31</sup>-1</td>
</tr>
<tr>
<td>unsigned long int</td>
<td>0 ~ 2<sup>32</sup>-1</td>
</tr>
</tbody>
</table>
<ul>
<li>
<p>short int至少16位，long int至少32位</p>
</li>
<li>
<p>头文件limits.h说明各种不同的整型的特点</p>
</li>
</ul>
<p><strong>一、整型常量</strong></p>
<ul>
<li>
<p>声明为const，初始化之后不能被改变</p>
</li>
<li>
<p>十进制整型常量可能是int、long、unsigned long。缺省情况下为最短类型但能完整容纳这个值</p>
</li>
<li>
<p>八进制整数以0开头</p>
</li>
<li>
<p>十六进制整数以0x开头</p>
</li>
<li>
<p>字符常量：类型为int，是单引号包围的单个字符</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;M&#x27;</span>			<span class="string">&#x27;\n&#x27;</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>宽字符常量：多字节字符常量的前面有个L</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">L&#x27;X&#x27;		L&#x27;e^&#x27;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p><strong>二、枚举类型</strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明类型</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">Jar_Type</span> &#123;</span>CUP, PINT, QUART, HALF_GALLON, GALLON&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义变量</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">Jar_Type</span> <span class="title">milk_jug</span>, <span class="title">gas_can</span>, <span class="title">medicine_bottle</span>;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>以整型方式存储，符号名实际值都是整型值。如CUP=0，PINT=1，以此类推</li>
<li>可以显式定值，若未指定值，则比前一个符号名大1</li>
</ul>
<h4 id="3-1-2-浮点类型">3.1.2 浮点类型</h4>
<ul>
<li>包括float、double、long double类型</li>
<li>所有浮点类型至少能容纳从10<sup>-37</sup>到10<sup>37</sup>之间的任何值</li>
<li>头文件float.h说明各种不同的浮点型的特点</li>
<li>浮点数默认为double类型；后面跟L/l表示long double；后面跟F/f表示float</li>
</ul>
<h4 id="3-1-3-指针">3.1.3 指针</h4>
<p><strong>一、指针常量</strong></p>
<ul>
<li>一般都通过操作符来获得一个变量的地址，而不是通过表示为字面值的指针常量，如0xff2044ec</li>
</ul>
<p><strong>二、字符串常量</strong></p>
<ul>
<li>字符串：以NUL字节结尾的零个或多个字符，存储在字符数组中</li>
<li>字符串常量：直接值是一个“指向字符的指针”，而不是这些字符本身</li>
</ul>
<h3 id="3-2-基本声明">3.2 基本声明</h3>
<h4 id="3-2-2-声明简单数组">3.2.2 声明简单数组</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> value[<span class="number">20</span>];</span><br></pre></td></tr></table></figure>
<ul>
<li>编译器不检查数组的下标是否在合法范围内，所以当下标是通过用户输入计算而来的，必须检测是否越界
<ul>
<li>如果越界，不会报错，只会返回null</li>
</ul>
</li>
</ul>
<h4 id="3-2-3-声明指针">3.2.3 声明指针</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *a;</span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> *message = <span class="string">&quot;Hello World&quot;</span>;</span><br><span class="line"><span class="comment">// 把message声明为一个指向字符的指针，并用字符串常量中的第1个字符的地址对其初始化</span></span><br><span class="line"><span class="comment">// 等价于以下语句</span></span><br><span class="line"><span class="keyword">char</span> *message;</span><br><span class="line">message = <span class="string">&quot;Hello World&quot;</span>;</span><br></pre></td></tr></table></figure>
<h3 id="3-3-typedef">3.3 typedef</h3>
<p>为各种数据类型定义新名字</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 将变量ptr_to_char声明为一个指向字符的指针类型的新名字</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">char</span> *ptr_to_char;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明a是一个指向字符的指针</span></span><br><span class="line">ptr_to_char a;</span><br></pre></td></tr></table></figure>
<h3 id="3-4-常量">3.4 常量</h3>
<p>const</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明整数常量</span></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> a;</span><br><span class="line"><span class="keyword">int</span> <span class="keyword">const</span> a;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个指向整型常量的指针</span></span><br><span class="line"><span class="keyword">int</span> <span class="keyword">const</span> *pci;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个指向整型的常量指针</span></span><br><span class="line"><span class="keyword">int</span> * <span class="keyword">const</span> cpi;</span><br></pre></td></tr></table></figure>
<p>#define</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX_LEN 20</span></span><br></pre></td></tr></table></figure>
<h3 id="3-5-作用域">3.5 作用域</h3>
<h4 id="3-5-1-代码块作用域">3.5.1 代码块作用域</h4>
<ul>
<li>
<p>代码块：位于一对花括号之间的所有语句</p>
</li>
<li>
<p>嵌套代码块中，内层可以访问外层变量，而外层无法访问内层变量，但是当内外层有名字相同的变量时，内层无法访问外层的那个同名变量</p>
</li>
<li>
<p>非嵌套的代码块中，作用域没有重叠，所以编译器可以把它们存储在同一个内存地址</p>
</li>
</ul>
<h4 id="3-5-2-文件作用域">3.5.2 文件作用域</h4>
<ul>
<li>任何在所有代码块之外声明的标识符都具有文件作用域，在声明处到源文件末尾都可以访问</li>
</ul>
<h4 id="3-5-3-原型作用域">3.5.3 原型作用域</h4>
<ul>
<li>只适用于在函数原型中声明的参数名</li>
</ul>
<h4 id="3-5-4-函数作用域">3.5.4 函数作用域</h4>
<ul>
<li>只适用于语句标签，语句标签用于goto语句</li>
</ul>
<h3 id="3-6-链接属性">3.6 链接属性</h3>
<p><strong>一、none 没有链接属性</strong></p>
<ul>
<li>声明的同名标识符被当作独立不同的实体</li>
</ul>
<p><strong>二、internal属性</strong></p>
<ul>
<li>单个文件中声明的同名标识符表示同一个实体</li>
</ul>
<p><strong>三、external属性</strong></p>
<ul>
<li>多个文件中声明的同名标识符表示同一个实体</li>
<li>只有具备文件作用域的标识符才能拥有external或internal的链接属性，其他作用域的标识符都是none属性。</li>
<li>默认情况下，具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符，无论在不同文件中声明多少次，表示的都是同一个实体。</li>
</ul>
<p><strong>四、关键字extern和static</strong></p>
<ul>
<li>如果某个标识符在正常情况下具有external链接属性(只能是具有文件作用域的标识符)，在其前面加上static关键字可以将其链接属性变为internal</li>
<li>链接属性只能修改一次，也就是说一旦将标识符的链接属性变为internal，就无法变回external了</li>
</ul>
<h3 id="3-7-存储类型">3.7 存储类型</h3>
<ul>
<li>存储变量的内存类型，有普通内存、运行时堆栈、硬件寄存器</li>
<li>在任何代码块之外声明的变量存储在<strong>静态内存</strong>中，为静态变量，在程序运行之前创建</li>
<li>在代码块内部声明的变量的缺省存储类型是自动的，即存储于<strong>堆栈</strong>中，进入代码块创建，离开代码块销毁
<ul>
<li>在代码块内部声明的变量加上static关键字，变为静态变量，但作用域不变。如在函数中声明static变量a，则a在程序开始执行时就被初始化，并且每次函数被调用时，a不会重新初始化</li>
</ul>
</li>
<li>关键字register声明自动变量，存储在<strong>硬件寄存器</strong>中，为寄存器变量</li>
</ul>
<p><strong>初始化</strong></p>
<ul>
<li>如果不显式指定初值，静态变量将初始化为0，而自动变量初始值不确定</li>
</ul>
<h3 id="3-8-static关键字">3.8 static关键字</h3>
<ul>
<li>用于函数定义或在代码块外声明变量时，将标识符的链接属性从external改为internal，但变量的存储类型和作用域不受影响</li>
<li>在代码块内部声明变量时将标识符的存储类型从自动变量改为静态变量，但变量的链接属性和作用域不受影响</li>
</ul>
<h3 id="3-9-总结">3.9 总结</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201028211529931.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201028211529931.png" srcset="" alt="image-20201028211529931"></p>
<h2 id="Ch4-语句">Ch4 语句</h2>
<h3 id="4-1-空语句">4.1 空语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">;</span><br></pre></td></tr></table></figure>
<p>只包含一个分号，不执行任何任务</p>
<h3 id="4-2-表达式语句">4.2 表达式语句</h3>
<ul>
<li>
<p>C不存在赋值语句，赋值通过表达式语句(在表达式之后加上一个分号)实现，如：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x = y + <span class="number">3</span>;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>以下语句也是合法的，但结果被立即丢弃：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">y + <span class="number">3</span>;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="4-3-代码块">4.3 代码块</h3>
<p>位于一对花括号之内的可选的声明和语句列表</p>
<h3 id="4-4-if语句">4.4 if语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (expression) &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>C语言不存在布尔变量，而使用整型的0和1代替，所以expression的结果不是0就是1</li>
</ul>
<h3 id="4-5-while语句">4.5 while语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (expression) &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>break终止所在while代码块的所有循环；continue终止所在while代码块的当前循环</li>
</ul>
<h3 id="4-6-for语句">4.6 for语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (初始化部分; 条件部分; 调整部分)&#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="4-7-do语句">4.7 do语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125; <span class="keyword">while</span> (expression);</span><br></pre></td></tr></table></figure>
<ul>
<li>循环体至少执行一次</li>
</ul>
<h3 id="4-8-switch语句">4.8 switch语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> (expression) &#123;</span><br><span class="line">    <span class="keyword">case</span> constant-expression<span class="number">-1</span>:</span><br><span class="line">        statement<span class="number">-1</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> constant-expression<span class="number">-2</span>:</span><br><span class="line">        statement<span class="number">-2</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>switch的条件expression必须为整型值</li>
<li>每个case标签必须具有唯一的值</li>
<li>每个switch语句都应该添加一条并且只能添加一条default语句，可以在case语句列表的任何位置</li>
</ul>
<h3 id="4-9-goto语句">4.9 goto语句</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">goto</span> 语句标签;</span><br></pre></td></tr></table></figure>
<ul>
<li>语句标签是在标识符后添加一个冒号，并跟上一些表达式语句</li>
<li>要尽可能避免使用goto语句</li>
</ul>
<h2 id="Ch5-操作符和表达式">Ch5 操作符和表达式</h2>
<h3 id="5-1-操作符">5.1 操作符</h3>
<h4 id="5-1-1-算术操作符">5.1.1 算术操作符</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">+ - * / %</span><br></pre></td></tr></table></figure>
<h4 id="5-1-2-移位操作符">5.1.2 移位操作符</h4>
<ul>
<li>
<p>左移：&lt;&lt;</p>
</li>
<li>
<p>右移：&gt;&gt;</p>
</li>
<li>
<p>无符号数的所有移位操作都是逻辑移位，有符号数是逻辑移位还是算术移位取决于编译器</p>
</li>
</ul>
<h4 id="5-1-3-位操作符">5.1.3 位操作符</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&amp; | ~</span><br><span class="line"><span class="comment">// 与或非</span></span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>将value指定位置1</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value = value | <span class="number">1</span> &lt;&lt; bit_number;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>将value指定位置0</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value = value &amp; ~ (<span class="number">1</span> &lt;&lt; bit_number);</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="5-1-5-单目操作符">5.1.5 单目操作符</h4>
<ul>
<li>
<p>!：逻辑取反，产生整型结果0或1</p>
</li>
<li>
<p>~：操作数每一位取反</p>
</li>
<li>
<p>-：取负</p>
</li>
<li>
<p>&amp;：取操作数的地址</p>
</li>
<li>
<p>*：间接访问，访问指针所指向的值</p>
</li>
<li>
<p>sizeof：判断操作数的类型长度，以字节为单位，操作数可以是变量，也可以是加上括号的类型</p>
<ul>
<li>sizeof (a = b + 1)并没有向a赋值</li>
</ul>
</li>
<li>
<p>强制类型转换，如获得整型变量a对应的浮点数值</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(<span class="keyword">float</span>) a</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>c+：增值操作符，<ins>a在变量被使用之前增加它的值，a</ins>在变量被使用之后增加它的值</p>
</li>
</ul>
<h4 id="5-1-6-关系操作符">5.1.6 关系操作符</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;  &gt;=    &lt;  &lt;=    ==  !=</span><br></pre></td></tr></table></figure>
<ul>
<li>产生的结果是整型的0或1</li>
</ul>
<h4 id="5-1-7-逻辑操作符">5.1.7 逻辑操作符</h4>
<ul>
<li>&amp;&amp;：对于expression1 &amp;&amp; expression2，若expression1为假，则不再对expression2求值</li>
<li>||：对于expression1 || expression2，若expression1为真，则不再对expression2求值</li>
</ul>
<h4 id="5-1-8-条件操作符">5.1.8 条件操作符</h4>
<p>expression1 ? expression2 : expression3</p>
<h3 id="5-2-布尔值">5.2 布尔值</h3>
<ul>
<li>C没有显式的布尔类型，用整数代替，0是假，任何非零值都是真</li>
</ul>
<h3 id="5-4-表达式求值">5.4 表达式求值</h3>
<ul>
<li>
<p>函数进行表达式求值时应该尽量避免以下形式：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">f() + g() + h()</span><br></pre></td></tr></table></figure>
<p>而使用以下形式，因为如果函数的返回值和执行顺序相关，则会产生不确定性</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">temp = f();</span><br><span class="line">temp += g();</span><br><span class="line">temp += h();</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="Ch6-指针">Ch6 指针</h2>
<h3 id="6-1-内存和地址">6.1 内存和地址</h3>
<ul>
<li>内存中的每个位置由一个独一无二的地址标识</li>
<li>内存中的每个位置都包含一个值</li>
<li>编译器帮助实现通过变量访问内存位置，但是硬件仍然通过地址访问内存位置</li>
</ul>
<h3 id="6-2-值和类型">6.2 值和类型</h3>
<p>不能简单地通过检查一个值的位来判断它的类型，因为不同的数据类型和指令会将其解释为不同的类型</p>
<h3 id="6-5-未初始化和非法的指针">6.5 未初始化和非法的指针</h3>
<p>在对指针进行间接访问之前，一定要进行初始化，下面是一个<strong>错误例子</strong>，因为指针a指向的位置不能确定：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *a;</span><br><span class="line">*a = <span class="number">12</span>;</span><br></pre></td></tr></table></figure>
<h3 id="6-6-NULL指针">6.6 NULL指针</h3>
<ul>
<li>
<p>NULL指针不指向任何东西</p>
</li>
<li>
<p>要使一个指针变量为NULL，可以给它赋一个零值；测试一个指针变量是否为NULL，可以将它与零值比较</p>
</li>
</ul>
<h3 id="6-7-指针、间接访问和左值">6.7 指针、间接访问和左值</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a;</span><br><span class="line"><span class="keyword">int</span> *d = &amp;a;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 合法，对指针d指向的值(a)进行修改</span></span><br><span class="line">*d = <span class="number">10</span> - *d;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 非法，整型数的计算结果赋给指针</span></span><br><span class="line">d = <span class="number">10</span> - *d;</span><br></pre></td></tr></table></figure>
<h3 id="6-10-指针的指针">6.10 指针的指针</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a = <span class="number">12</span>;</span><br><span class="line"><span class="keyword">int</span> *b = &amp;a;</span><br><span class="line"><span class="keyword">int</span> **c = &amp;b;</span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>表达式</th>
<th>相当的表达式</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>12</td>
</tr>
<tr>
<td>b</td>
<td>&amp;a</td>
</tr>
<tr>
<td>*b</td>
<td>a, 12</td>
</tr>
<tr>
<td>c</td>
<td>&amp;b</td>
</tr>
<tr>
<td>*c</td>
<td>b, &amp;a</td>
</tr>
<tr>
<td>**c</td>
<td>*b, a, 12</td>
</tr>
</tbody>
</table>
<h3 id="6-11-指针表达式">6.11 指针表达式</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112510530.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112510530.png" srcset="" alt="image-20201030112510530"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112528313.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112528313.png" srcset="" alt="image-20201030112528313"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112553253.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112553253.png" srcset="" alt="image-20201030112553253"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112611434.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112611434.png" srcset="" alt="image-20201030112611434"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112624338.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112624338.png" srcset="" alt="image-20201030112624338"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112817215.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112817215.png" srcset="" alt="image-20201030112817215"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112834050.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112834050.png" srcset="" alt="image-20201030112834050"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112852658.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112852658.png" srcset="" alt="image-20201030112852658"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112905585.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112905585.png" srcset="" alt="image-20201030112905585"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112918911.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112918911.png" srcset="" alt="image-20201030112918911"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112931420.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112931420.png" srcset="" alt="image-20201030112931420"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112944852.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112944852.png" srcset="" alt="image-20201030112944852"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112958540.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030112958540.png" srcset="" alt="image-20201030112958540"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030113010189.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030113010189.png" srcset="" alt="image-20201030113010189"></p>
<h3 id="6-13-指针运算">6.13 指针运算</h3>
<h4 id="6-13-1-算术运算">6.13.1 算术运算</h4>
<ul>
<li>当一个指针和一个整数量执行算术运算时，整数在执行加法运算前始终会根据对应变量的类型的长度进行调整。例如若float类型指针变量p占4个字节，则p+1不会指向p的第二字节，而是会指向p所占的4个字节之后的那个字节</li>
<li>两个指针只有当都指向同一个数组中的元素时，才允许进行相减，并且减法的结果是两个元素在数组中的距离，而不是内存地址的差值，即在减法运算的同时会除掉变量类型的长度</li>
</ul>
<h4 id="6-13-2-关系运算">6.13.2 关系运算</h4>
<p>对于指向同一个数组中的元素的指针，可以用关系操作符(<code>&gt; &lt; &gt;= &lt;=</code>)来判断哪个指针指向数组中更前或更后的元素</p>
<h2 id="Ch7-函数">Ch7 函数</h2>
<h3 id="7-2-函数声明">7.2 函数声明</h3>
<h4 id="7-2-1-原型">7.2.1 原型</h4>
<ul>
<li>
<p>原型总结了函数定义的起始部分的声明，向编译器提供有关函数应该如何调用的完整信息</p>
</li>
<li>
<p>函数原型的使用：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// func_use.c</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;func.h&quot;</span></span></span><br><span class="line">...</span><br><span class="line">    </span><br><span class="line"><span class="comment">// func.h</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> *<span class="title">func</span><span class="params">(<span class="keyword">int</span> *value, <span class="keyword">int</span> len)</span></span>;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>声明一个没有参数的函数原型：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> *<span class="title">func</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="7-2-2-函数的缺省认定">7.2.2 函数的缺省认定</h4>
<p>当程序调用一个无法见到原型的函数时，编译器会认为该函数返回一个整型</p>
<h3 id="7-3-函数的参数">7.3 函数的参数</h3>
<ul>
<li>所有参数都是<strong>传值调用</strong>，函数不会修改实际传递的参数</li>
<li>当传递的参数是指针时，可以通过指针的间接访问修改指针所指的值，称为<strong>传址调用</strong></li>
</ul>
<h3 id="7-4-ADT和黑盒">7.4 ADT和黑盒</h3>
<p>使用static关键字限制对非接口函数和数据的访问</p>
<h3 id="7-5-递归">7.5 递归</h3>
<ul>
<li>通过运行时堆栈支持递归函数的实现</li>
</ul>
<p>通过一个简单的递归作为实例：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接受一个整型值(无符号)，把它转换为字符并打印，前导零被删除</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">binary_to_ascii</span><span class="params">(<span class="keyword">unsigned</span> <span class="keyword">int</span> value)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">int</span> quotient;</span><br><span class="line">    </span><br><span class="line">    quotient = value / <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">if</span> (quotient != <span class="number">0</span>) &#123;</span><br><span class="line">        binary_to_ascii(quotient);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">putchar</span>(value % <span class="number">10</span> + <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="7-5-1-追踪递归函数">7.5.1 追踪递归函数</h4>
<p>程序运行时堆栈的变化：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144906982.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144906982.png" srcset="" alt="image-20201030144906982"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144921304.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144921304.png" srcset="" alt="image-20201030144921304"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144933258.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144933258.png" srcset="" alt="image-20201030144933258"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144943300.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144943300.png" srcset="" alt="image-20201030144943300"></p>
<p>​															…</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144956035.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030144956035.png" srcset="" alt="image-20201030144956035"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145042009.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145042009.png" srcset="" alt="image-20201030145042009"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145053160.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145053160.png" srcset="" alt="image-20201030145053160"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145101621.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145101621.png" srcset="" alt="image-20201030145101621"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145110915.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030145110915.png" srcset="" alt="image-20201030145110915"></p>
<h4 id="7-5-2-递归与迭代">7.5.2 递归与迭代</h4>
<ul>
<li>如果一个递归函数内部所执行的最后一条语句就是调用自身时，被称为尾部递归，这样的递归很容易被改写为循环迭代的形式，而迭代的效率通常较高</li>
</ul>
<h3 id="7-6-可变参数列表">7.6 可变参数列表</h3>
<h4 id="7-6-1-stdarg宏">7.6.1 stdarg宏</h4>
<p>定义于stdarg.h头文件</p>
<ul>
<li>类型va_list：用于声明变量来访问参数列表的未确定部分
<ul>
<li>此时声明函数的方式为<code>float average(int n, ...)</code></li>
</ul>
</li>
<li>宏va_start：初始化va_list声明的变量，第1个参数是va_list变量名，第2个参数是省略号前的最后一个有名字的参数</li>
<li>宏va_arg：用于访问参数，第1个参数是va_list变量名，第2个参数是参数列表中下一个参数的类型，返回这个参数的值，并指向下一个可变参数</li>
<li>宏va_end：访问完最后一个可变参数后调用，参数为va_list变量名</li>
</ul>
<h4 id="7-6-2-可变参数的限制">7.6.2 可变参数的限制</h4>
<ul>
<li>这些宏无法判断实际存在的参数的数量</li>
<li>这些宏无法判断每个参数的类型</li>
</ul>
<h2 id="Ch8-数组">Ch8 数组</h2>
<h3 id="8-1-一维数组">8.1 一维数组</h3>
<h4 id="8-1-1-数组名">8.1.1 数组名</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> b[<span class="number">10</span>];</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>b[3]的类型是整型</p>
</li>
<li>
<p>b是一个指向b[0]的常量指针，因而不能修改数组名的值，即不能修改数组存储的内存地址</p>
</li>
<li>
<p>数组的赋值</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a[<span class="number">10</span>];</span><br><span class="line"><span class="keyword">int</span> b[<span class="number">10</span>];</span><br><span class="line"><span class="keyword">int</span> *c;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 以下两个表达式作用相同，将c指向a[0]</span></span><br><span class="line">c = &amp;a[<span class="number">0</span>];</span><br><span class="line">c = a;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>// 以下表达式非法，不能将数组复制给数组，数组间的复制只能通过循环逐个元素复制<br>
b = a;</p>
<p>// 以下表达式非法，a是常量，不能被修改<br>
a = c;</p>
  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">  </span><br><span class="line"></span><br><span class="line">#### 8.1.2 下标引用</span><br><span class="line"></span><br><span class="line">通过以下例子说明：</span><br><span class="line"></span><br><span class="line">​&#96;&#96;&#96;c</span><br><span class="line">int array[10];</span><br><span class="line">int *ap &#x3D; array + 2;</span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>表达式</th>
<th>对等表达式</th>
</tr>
</thead>
<tbody>
<tr>
<td>ap</td>
<td>array+2, &amp;array[2]</td>
</tr>
<tr>
<td>*ap</td>
<td>array[2], *(array+2)</td>
</tr>
<tr>
<td>ap[0]</td>
<td>array[2]</td>
</tr>
<tr>
<td>ap+6</td>
<td>array+8, &amp;array[8]</td>
</tr>
<tr>
<td>*ap+6</td>
<td>array[2]+6</td>
</tr>
<tr>
<td>*(ap+6)</td>
<td>array[8]</td>
</tr>
<tr>
<td>ap[-1]</td>
<td>array[1]</td>
</tr>
<tr>
<td>ap[9]</td>
<td>非法</td>
</tr>
</tbody>
</table>
<h4 id="8-1-3-指针与下标">8.1.3 指针与下标</h4>
<p>指针有时比下标更加高效</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030172144100.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030172144100.png" srcset="" alt="image-20201030172144100"></p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030172236189.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030172236189.png" srcset="" alt="image-20201030172236189"></p>
<ul>
<li>在数组中一次一步移动时，与固定数字相乘的运算在编译的时候完成，所以在运行时所需的指令就少</li>
<li>但这在实际中不常用，因为可能编译器对循环会有优化</li>
</ul>
<h4 id="8-1-5-数组和指针">8.1.5 数组和指针</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a[<span class="number">5</span>];   <span class="comment">// 数组</span></span><br><span class="line"><span class="keyword">int</span> *b;     <span class="comment">// 指针</span></span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>a和b都具有指针值，都可以进行间接访问和下标引用操作</p>
</li>
<li>
<p>区别：</p>
<ul>
<li>声明数组时，编译器会为数组保留内存空间，然后再创建数组名</li>
<li>声明指针变量时，编译器只为指针本身保留内存空间，而不为整型值分配内存空间</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030175554658.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030175554658.png" srcset="" alt="image-20201030175554658"></p>
</li>
<li>
<p>在上述声明后：</p>
<ul>
<li>*a是合法的，*b是非法的，因为*b将访问内存中某个不确定的位置</li>
<li>b<ins>是合法的，a</ins>是非法的，因为a是常量指针</li>
</ul>
</li>
</ul>
<h4 id="8-1-7-声明数组参数">8.1.7 声明数组参数</h4>
<p>下面的函数原型是等价的：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">strlen</span><span class="params">(<span class="keyword">char</span> *<span class="built_in">string</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">strlen</span><span class="params">(<span class="keyword">char</span> <span class="built_in">string</span>[])</span></span>;</span><br></pre></td></tr></table></figure>
<h4 id="8-1-8-初始化">8.1.8 初始化</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> <span class="built_in">vector</span>[<span class="number">5</span>] = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>&#125;;</span><br></pre></td></tr></table></figure>
<ul>
<li>静态初始化：静态变量存储在静态内存，只初始化一次</li>
<li>自动初始化：自动变量在缺省情况下是未初始化的，若给定初值，则每次进入代码块都会重新初始化</li>
</ul>
<h4 id="8-1-9-不完整的初始化">8.1.9 不完整的初始化</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> <span class="built_in">vector</span>[<span class="number">5</span>] = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>&#125;;</span><br></pre></td></tr></table></figure>
<p>vector[4]被初始化为0</p>
<h4 id="8-1-10-自动计算数组长度">8.1.10 自动计算数组长度</h4>
<p>如果声明中未给出数组的长度，编译器就把数组的长度设置为刚好能够容纳所有初始值的长度</p>
<h4 id="8-1-11-字符数组的初始化">8.1.11 字符数组的初始化</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 初始化一个字符串数组</span></span><br><span class="line"><span class="keyword">char</span> message1[] = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化一个字符串常量</span></span><br><span class="line"><span class="keyword">char</span> *message2 = <span class="string">&quot;Hello&quot;</span>;</span><br></pre></td></tr></table></figure>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030233429373.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030233429373.png" srcset="" alt="image-20201030233429373"></p>
<h3 id="8-2-多维数组">8.2 多维数组</h3>
<h4 id="8-2-1-存储顺序">8.2.1 存储顺序</h4>
<p>定义一个数组：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> <span class="built_in">array</span>[<span class="number">3</span>][<span class="number">6</span>];</span><br></pre></td></tr></table></figure>
<p>其在内存中的存储形式为：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030235423211.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201030235423211.png" srcset="" alt="image-20201030235423211"></p>
<p>这18个元素的下标值依次是(0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (1,0) … (2,4) (2,5)</p>
<h4 id="8-2-2-数组名">8.2.2 数组名</h4>
<p>如在<code>int matrix[3][10]</code>中，matrix是指向一个包含10个整型元素的数组的指针</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000129705.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000129705.png" srcset="" alt="image-20201031000129705"></p>
<p>那么matrix+1则指向：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000214011.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000214011.png" srcset="" alt="image-20201031000214011"></p>
<p>而*(matrix + 1) + 5就等价于matrix[1] + 5，是一个指向整型的指针：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000530029.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031000530029.png" srcset="" alt="image-20201031000530029"></p>
<h4 id="8-2-4-指向数组的指针">8.2.4 指向数组的指针</h4>
<p>声明一个指向整型数组的指针，并令其指向matrix数组的第一行：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> (*p)[<span class="number">10</span>] = matrix;</span><br></pre></td></tr></table></figure>
<h4 id="8-2-5-作为函数参数的多维数组">8.2.5 作为函数参数的多维数组</h4>
<p>可以使用以下两张形式的任何一种：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> (*mat)[<span class="number">10</span>])</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> mat[][<span class="number">10</span>])</span></span>;</span><br></pre></td></tr></table></figure>
<h4 id="8-2-6-初始化">8.2.6 初始化</h4>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031171919198.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031171919198.png" srcset="" alt="image-20201031171919198"></p>
<h4 id="8-2-7-数组长度自动计算">8.2.7 数组长度自动计算</h4>
<p>在多维数组中，只有第1维才能根据初始化列表缺省地提供，剩余的几个维必须显式写出</p>
<h3 id="8-3-指针数组">8.3 指针数组</h3>
<p>定义方式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> <span class="keyword">const</span> *keyword[] = &#123;</span><br><span class="line">    <span class="string">&quot;do&quot;</span>,</span><br><span class="line">    <span class="string">&quot;for&quot;</span>,</span><br><span class="line">    <span class="string">&quot;if&quot;</span>,</span><br><span class="line">    <span class="string">&quot;return&quot;</span>,</span><br><span class="line">    <span class="literal">NULL</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这样定义的好处在于如果要遍历这个表，只需要<code>for (kwp=keyword; *kwp!=NULL; kwp++)</code></p>
<h2 id="Ch9-字符串、字符和字节">Ch9 字符串、字符和字节</h2>
<h3 id="9-1-字符串基础">9.1 字符串基础</h3>
<ul>
<li>字符串的长度不包含最后的NUL字节</li>
<li>头文件string.h包含了使用字符串函数所需的原型和声明</li>
</ul>
<h3 id="9-2-字符串长度">9.2 字符串长度</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">size_t</span> <span class="title">strlen</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *<span class="built_in">string</span>)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>返回类型为size_t，是一个无符号整数类型</p>
</li>
<li>
<p>不要在表达式中同时包含有符号数和无符号数，因此应该把strlen的返回值<strong>强制转换为int</strong></p>
</li>
</ul>
<h3 id="9-3-不受限制的字符串函数">9.3 不受限制的字符串函数</h3>
<h4 id="9-3-1-复制字符串">9.3.1 复制字符串</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strcpy</span><span class="params">(<span class="keyword">char</span> *dst, <span class="keyword">char</span> <span class="keyword">const</span> *src)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>dst必须是一个字符数组或是一个指向动态分配内存的数组的指针</li>
<li>复制字符串前必须保证目标字符数组的空间足以容纳需要复制的字符串，不然会覆盖数组之后内存的内容</li>
</ul>
<h4 id="9-3-2-连接字符串">9.3.2 连接字符串</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strcat</span><span class="params">(<span class="keyword">char</span> *dst, <span class="keyword">char</span> <span class="keyword">const</span> *src)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>将src字符串的拷贝添加到dst字符串之后</li>
</ul>
<h4 id="9-3-4-字符串比较">9.3.4 字符串比较</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">strcmp</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *s1, <span class="keyword">char</span> <span class="keyword">const</span> *s2)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>若s1小于s2，返回一个小于0的值；若s1大于s2，返回一个大于0的值；若s1和s2相等，返回0</li>
</ul>
<h3 id="9-4-长度受限的字符串函数">9.4 长度受限的字符串函数</h3>
<ul>
<li>
<p>字符串复制，将src的前len个字符(不够补NUL)复制给dst，但当src的长度大于len时，只能复制len个字符给dst，因此结果的dst最后是没有NUL的</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strncpy</span><span class="params">(<span class="keyword">char</span> *dst, <span class="keyword">char</span> <span class="keyword">const</span> *src, <span class="keyword">size_t</span> len)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>字符串连接，将src的前len个字符(不够补NUL)连接到dst后面，会自动添加一个NUL在dst的最后</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strncat</span><span class="params">(<span class="keyword">char</span> *dst, <span class="keyword">char</span> <span class="keyword">const</span> *src, <span class="keyword">size_t</span> len)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>字符串比较，比较两个字符串的前len位</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">strncmp</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *s1, <span class="keyword">char</span> <span class="keyword">const</span> *s2, <span class="keyword">size_t</span> len)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="9-5-字符串查找基础">9.5 字符串查找基础</h3>
<h4 id="9-5-1-查找一个字符">9.5.1 查找一个字符</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strchr</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *str, <span class="keyword">int</span> ch)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strrchr</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *str, <span class="keyword">int</span> ch)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>在字符串str中查找字符ch第一次出现的位置，返回一个指向该位置的指针，若没有找到返回NULL指针</li>
<li>strchr从左开始找，strrchr从右开始找</li>
</ul>
<h4 id="9-5-2-查找任何几个字符">9.5.2 查找任何几个字符</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strpbrk</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *str, <span class="keyword">char</span> <span class="keyword">const</span> *group)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>返回一个指向str中第一个匹配group中任何一个字符的位置指针</li>
</ul>
<h4 id="9-5-3-查找一个子串">9.5.3 查找一个子串</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strstr</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *s1, <span class="keyword">char</span> <span class="keyword">const</span> *s2)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>在s1中查找整个s2第一次出现的起始位置，并返回一个指向该位置的指针</li>
</ul>
<h3 id="9-6-高级字符串查找">9.6 高级字符串查找</h3>
<h4 id="9-6-1-查找一个字符串前缀">9.6.1 查找一个字符串前缀</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">size_t</span> <span class="title">strspn</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *str, <span class="keyword">char</span> <span class="keyword">const</span> *group)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">size_t</span> <span class="title">strcspn</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *str, <span class="keyword">char</span> <span class="keyword">const</span> *group)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>strspn返回str起始部分匹配group中任意字符的字符数，而strcspn找的是非group中的字符</p>
</li>
<li>
<p>例如得到指向字符串中第一个非空白字符：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">prt = buffer + <span class="built_in">strspn</span>(buffer, <span class="string">&quot;\n\t\r\f\v&quot;</span>);</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="9-6-2-查找标记">9.6.2 查找标记</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strtok</span><span class="params">(<span class="keyword">char</span> *str, <span class="keyword">char</span> <span class="keyword">const</span> *sep)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>从字符串中隔离各个单独的称为标记的部分</p>
</li>
<li>
<p>sep定义了用作分隔符的字符集合</p>
</li>
<li>
<p>若strtok的第一个参数不是NULL，函数将找到字符串的第一个标记，同时保存它在字符串中的位置；若strtok的第一个参数是NULL，函数将在同一个字符串中从保存的位置开始查找下一个标记；若找不到下一个标记，则返回NULL</p>
</li>
<li>
<p>例子：查找被空白分隔的单词</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (token=strtok(line, whitespace); token!=<span class="literal">NULL</span>; token=strtok(<span class="literal">NULL</span>, whitespace)) &#123;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;%s\n&quot;</span>, token);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="9-7-错误信息">9.7 错误信息</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">strerror</span><span class="params">(<span class="keyword">int</span> error_number)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>参数为错误代码，返回一个指向用于描述错误的字符串的指针</li>
</ul>
<h3 id="9-8-字符操作">9.8 字符操作</h3>
<p>头文件ctype.h</p>
<h4 id="9-8-1-字符分类">9.8.1 字符分类</h4>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031215526209.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201031215526209.png" srcset="" alt="image-20201031215526209"  />
<h4 id="9-8-2-字符大小写转换">9.8.2 字符大小写转换</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">tolower</span><span class="params">(<span class="keyword">int</span> ch)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">toupper</span><span class="params">(<span class="keyword">int</span> ch)</span></span>;</span><br></pre></td></tr></table></figure>
<h3 id="9-9-内存操作">9.9 内存操作</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memcpy</span><span class="params">(<span class="keyword">void</span> *dst, <span class="keyword">void</span> <span class="keyword">const</span> *src, <span class="keyword">size_t</span> length)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memmove</span><span class="params">(<span class="keyword">void</span> *dst, <span class="keyword">void</span> <span class="keyword">const</span> *src, <span class="keyword">size_t</span> length)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memcmp</span><span class="params">(<span class="keyword">void</span> <span class="keyword">const</span> *a, <span class="keyword">void</span> <span class="keyword">const</span> *b, <span class="keyword">size_t</span> length)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memchr</span><span class="params">(<span class="keyword">void</span> <span class="keyword">const</span> *a, <span class="keyword">int</span> ch, <span class="keyword">size_t</span> length)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memset</span><span class="params">(<span class="keyword">void</span> *a, <span class="keyword">int</span> ch, <span class="keyword">size_t</span> length)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>与strn带头的函数不同，这些函数遇到NUL字节时不会停止操作</li>
</ul>
<h2 id="Ch10-结构和联合">Ch10 结构和联合</h2>
<h3 id="10-1-结构基础知识">10.1 结构基础知识</h3>
<p>当一个结构变量在表达式中使用时，并不被替换成一个指针，而是一个标量类型</p>
<h4 id="10-1-1-结构声明">10.1.1 结构声明</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">char</span> b;</span><br><span class="line">    <span class="keyword">float</span> c;</span><br><span class="line">&#125; x, y[<span class="number">20</span>], *z;</span><br></pre></td></tr></table></figure>
<ul>
<li>声明了结构体x，包含20个结构体的数组y，指向结构体的指针z</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SIMPLE</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">char</span> b;</span><br><span class="line">    <span class="keyword">float</span> c;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SIMPLE</span> <span class="title">x</span>, <span class="title">y</span>[20], *<span class="title">z</span>;</span></span><br></pre></td></tr></table></figure>
<p>推荐使用以下声明方法：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">char</span> b;</span><br><span class="line">    <span class="keyword">float</span> c;</span><br><span class="line">&#125; Simple;</span><br><span class="line"></span><br><span class="line">Simple x, y[<span class="number">20</span>], *z;</span><br></pre></td></tr></table></figure>
<h4 id="10-1-2-结构成员">10.1.2 结构成员</h4>
<ul>
<li>
<p>直接访问：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Simple simp;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 访问成员a</span></span><br><span class="line">simp.a</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>间接访问：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Simple *simp;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 访问成员a</span></span><br><span class="line">simp-&gt;a</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="10-1-5-结构的自引用">10.1.5 结构的自引用</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 错误</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF</span> <span class="title">b</span>;</span></span><br><span class="line">    <span class="keyword">int</span> c;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF</span> *<span class="title">b</span>;</span></span><br><span class="line">    <span class="keyword">int</span> c;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 错误</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF</span> *<span class="title">b</span>;</span></span><br><span class="line">    <span class="keyword">int</span> c;</span><br><span class="line">&#125; SELF_REF;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF_TAG</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">SELF_REF_TAG</span> *<span class="title">b</span>;</span></span><br><span class="line">    <span class="keyword">int</span> c;</span><br><span class="line">&#125; SELF_REF;</span><br></pre></td></tr></table></figure>
<h4 id="10-1-6-不完整的声明">10.1.6 不完整的声明</h4>
<p>用于多个相互依赖的结构体之间的声明</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">B</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">A</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">B</span> *<span class="title">partner</span>;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">B</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">A</span> *<span class="title">partner</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h3 id="10-2-结构、指针和成员">10.2 结构、指针和成员</h3>
<p>后面几节都以以下结构体为例：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">short</span> b[<span class="number">2</span>];</span><br><span class="line">&#125; Ex2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">Ex</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">char</span> b[<span class="number">3</span>];</span><br><span class="line">    Ex2 c;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">EX</span> *<span class="title">d</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101184819038.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101184819038.png" srcset="" alt="image-20201101184819038" style="zoom:80%;" />
<p>若声明一个结构体：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Ex x = &#123;<span class="number">10</span>, <span class="string">&quot;Hi&quot;</span>, &#123;<span class="number">5</span>, &#123;<span class="number">-1</span>, <span class="number">25</span>&#125;&#125;, <span class="number">0</span>&#125;;</span><br><span class="line">Ex *px = &amp;x;</span><br></pre></td></tr></table></figure>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101184841055.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101184841055.png" srcset="" alt="image-20201101184841055"></p>
<h4 id="10-2-1-访问指针">10.2.1 访问指针</h4>
<ul>
<li>px的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185055208.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185055208.png" srcset="" alt="image-20201101185055208"></p>
<ul>
<li>px的左值：
<ul>
<li>px+1是一个非法的左值</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185116789.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185116789.png" srcset="" alt="image-20201101185116789"></p>
<h4 id="10-2-2-访问结构">10.2.2 访问结构</h4>
<ul>
<li>*px的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185329988.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185329988.png" srcset="" alt="image-20201101185329988"></p>
<ul>
<li>*px的左值（接受一个新值）：
<ul>
<li>*px+1是非法的，因为没办法将结构体和整型相加</li>
<li>*(px+1)也是非法的</li>
</ul>
</li>
</ul>
<h4 id="image-2020110118534746710-2-3-访问结构成员"><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185347467.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185347467.png" srcset="" alt="image-20201101185347467">10.2.3 访问结构成员</h4>
<ul>
<li>px-&gt;a的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185553782.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185553782.png" srcset="" alt="image-20201101185553782"></p>
<ul>
<li>
<p>如果进行以下声明：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *pi;</span><br><span class="line">pi = &amp;px-&gt;a;</span><br></pre></td></tr></table></figure>
<p>则pi为：</p>
</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185756719.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101185756719.png" srcset="" alt="image-20201101185756719"></p>
<p>​	**注：**<em>px的结果是整个结构，而</em>pi的结果是一个整型数</p>
<ul>
<li>px-&gt;b的右值为指针常量，所以没有合法左值：
<ul>
<li>对数组元素的访问采用px-&gt;b[1]</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190015612.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190015612.png" srcset="" alt="image-20201101190015612"></p>
<h4 id="10-2-4-访问嵌套的结构">10.2.4 访问嵌套的结构</h4>
<ul>
<li>px-&gt;c的左值是整个结构，右值如下：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190226613.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190226613.png" srcset="" alt="image-20201101190226613"></p>
<ul>
<li>px-&gt;c.a的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190313143.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190313143.png" srcset="" alt="image-20201101190313143"></p>
<ul>
<li>*px-&gt;c.b的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190339608.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190339608.png" srcset="" alt="image-20201101190339608"></p>
<h4 id="10-2-5-访问指针成员">10.2.5 访问指针成员</h4>
<p>对px-&gt;d进行初始化，使其指向一个结构体：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Ex y;</span><br><span class="line">px-&gt;d = &amp;y;</span><br></pre></td></tr></table></figure>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190547718.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190547718.png" srcset="" alt="image-20201101190547718"></p>
<ul>
<li>px-&gt;d-&gt;c.b[1]的右值：</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190624854.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101190624854.png" srcset="" alt="image-20201101190624854"></p>
<h3 id="10-3-结构的存储分配">10.3 结构的存储分配</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ALIGN</span> &#123;</span></span><br><span class="line">    <span class="keyword">char</span> a;</span><br><span class="line">    <span class="keyword">int</span> b;</span><br><span class="line">    <span class="keyword">char</span> c;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>对于上述结构体，若整型长度为4字节，而且它的起始存储位置必须能被4整除，于是a存储为1字节，但是后面必须空出3字节才能存放b，其存储形式为：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101191932308.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201101191932308.png" srcset="" alt="image-20201101191932308"></p>
<p>一个结构体占了12个字节的存储空间，有效利用空间却只有6字节</p>
<p>如果声明改为如下形式，则只需要8个字节就能存储这个结构体：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ALIGN</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> b;</span><br><span class="line">    <span class="keyword">char</span> a;</span><br><span class="line">    <span class="keyword">char</span> c;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<ul>
<li>sizeof可以得出一个结构体的整体长度，包括跳过的字节</li>
<li>使用offset(type, member)能获得结构体中某成员的实际位置，如offset(struct ALIGN, b)</li>
</ul>
<h3 id="10-4-作为函数参数的结构">10.4 作为函数参数的结构</h3>
<ul>
<li>
<p>最好使用指针来传递参数，并声明为寄存器变量来提高效率</p>
<ul>
<li>
<p>若结构体成员不能改变，则：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test</span><span class="params">(<span class="keyword">register</span> ALIGN <span class="keyword">const</span> *test)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>若需要根据程序运行结果修改结构体中的值，则：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test</span><span class="params">(<span class="keyword">register</span> ALIGN *test)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>调用方式都为：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">test(&amp;align);</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<h3 id="10-5-位段">10.5 位段</h3>
<ul>
<li>注重可移植性的程序应该避免使用位段</li>
</ul>
<h3 id="10-6-联合">10.6 联合</h3>
<ul>
<li>
<p>联合的所有成员引用的是内存中的相同位置</p>
</li>
<li>
<p>如果联合的各个成员具有不同的长度，联合的长度就是最长成员的长度</p>
</li>
<li>
<p>应用场景比如：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">VARIABLE</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">enum</span> &#123;</span>INT, FLOAT, STRING&#125; type;</span><br><span class="line">    <span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">        <span class="keyword">int</span> i;</span><br><span class="line">        <span class="keyword">float</span> f;</span><br><span class="line">        <span class="keyword">char</span> *s;</span><br><span class="line">    &#125; value;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>对于整型，type设为INT，存储于value.i中；对于浮点数，type设为FLOAT，存储于value.f中；</p>
</li>
<li>
<p>联合的初始化，初始值必须是联合第一个成员的类型，如</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> a;</span><br><span class="line">    <span class="keyword">float</span> b;</span><br><span class="line">    <span class="keyword">char</span> c[<span class="number">4</span>];</span><br><span class="line">&#125; x = &#123;<span class="number">5</span>&#125;;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="Ch11-动态内存分配">Ch11 动态内存分配</h2>
<h3 id="11-1-为什么使用动态分配内存">11.1 为什么使用动态分配内存</h3>
<p>声明数组时，数组的长度往往在运行时才能知道，但是编译时需要指定数组的长度，因为需要提前开辟内存空间。</p>
<h3 id="11-2-malloc和free">11.2 malloc和free</h3>
<ul>
<li>在头文件stdlib.h中声明</li>
</ul>
<h4 id="11-2-1-malloc">11.2.1 malloc</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">malloc</span><span class="params">(<span class="keyword">size_t</span> size)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>malloc从内存池中提取一块合适的内存，并返回一个指向这块内存起始位置的指针(如果内存池中的内存可以满足需求的话，否则返回NULL)</li>
<li>参数是需要分配的内存字节数</li>
<li>malloc分配的是一块连续的内存</li>
<li>分配的内存不会被初始化</li>
</ul>
<h4 id="11-2-2-free">11.2.2 free</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">free</span><span class="params">(<span class="keyword">void</span> *pointer)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>参数是NULL时不会产生任何效果</li>
<li>参数是先前从malloc、calloc或realloc返回的值时，将分配的内存归还给内存池</li>
</ul>
<h3 id="11-3-calloc和realloc">11.3 calloc和realloc</h3>
<h4 id="11-3-1-calloc">11.3.1 calloc</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">calloc</span><span class="params">(<span class="keyword">size_t</span> num_elements, <span class="keyword">size_t</span> element_size)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>参数包括所需元素的数量和每个元素的字节数</li>
<li>将分配的内存初始化为0</li>
</ul>
<h4 id="11-3-2-realloc">11.3.2 realloc</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">realloc</span><span class="params">(<span class="keyword">void</span> *ptr, <span class="keyword">size_t</span> new_size)</span></span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>用于修改一个原先已经分配的内存块的大小</li>
<li>扩大内存块时，在原先的内存块之后添加；缩小内存块时，从原先内存块的尾部删除</li>
</ul>
<h3 id="11-4-使用动态分配的内存">11.4 使用动态分配的内存</h3>
<ul>
<li>
<p>获得足够存储25个整型的内存</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *pi;</span><br><span class="line">pi = <span class="built_in">malloc</span>(<span class="number">25</span> * <span class="keyword">sizeof</span>(<span class="keyword">int</span>));</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="11-5-常见的动态内存错误">11.5 常见的动态内存错误</h3>
<ul>
<li>
<p>对NULL指针进行解引用操作</p>
</li>
<li>
<p>对分配的内存进行操作时越界</p>
</li>
<li>
<p>释放并非动态分配的内存</p>
</li>
<li>
<p>试图释放一块动态分配的内存的一部分</p>
</li>
<li>
<p>一块动态内存被释放之后被继续使用</p>
</li>
<li>
<p>内存泄漏：在使用完毕动态内存后没有进行释放</p>
</li>
</ul>
<h2 id="Ch12-使用结构和指针">Ch12 使用结构和指针</h2>
<h3 id="12-2-单链表">12.2 单链表</h3>
<p>声明一个节点：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">NODE</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">NODE</span> *<span class="title">link</span>;</span></span><br><span class="line">    <span class="keyword">int</span> value;</span><br><span class="line">&#125; Node;</span><br></pre></td></tr></table></figure>
<p>链表结构如图所示：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201105130430994.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201105130430994.png" srcset="" alt="image-20201105130430994"></p>
<h4 id="12-2-1-插入一个有序单链表">12.2.1 插入一个有序单链表</h4>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数的参数是一个指向链表第一个节点的指针，以及一个需要插入的新值</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;sll_node.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> FALSE 0</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE 1</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">sll_insert</span><span class="params">(<span class="keyword">register</span> Node **linkp, <span class="keyword">int</span> new_value)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">register</span> Node *current;</span><br><span class="line">    <span class="keyword">register</span> Node *<span class="keyword">new</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 寻找正确的插入位置</span></span><br><span class="line">    <span class="keyword">while</span> ((current=*linkp) != <span class="literal">NULL</span> &amp;&amp; current-&gt;value &lt; new_value) &#123;</span><br><span class="line">        linkp = &amp;current-&gt;link;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 为新节点分配内存</span></span><br><span class="line">    <span class="keyword">new</span> = (Node *)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">new</span> == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> FALSE;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">new</span>-&gt;value = new_value;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 插入节点</span></span><br><span class="line">    <span class="keyword">new</span>-&gt;link = current;</span><br><span class="line">    *linkp = <span class="keyword">new</span>;</span><br><span class="line">    <span class="keyword">return</span> TRUE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="12-3-双链表">12.3 双链表</h3>
<p>声明一个双链表节点:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">NODE</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">NODE</span> *<span class="title">fwd</span>;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">NODE</span> *<span class="title">bwd</span>;</span></span><br><span class="line">    <span class="keyword">int</span> value;</span><br><span class="line">&#125; Node;</span><br></pre></td></tr></table></figure>
<p>双链表结构如图所示：</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201105133824925.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/Pointers-on-c-Notes/image-20201105133824925.png" srcset="" alt="image-20201105133824925"></p>
<h2 id="Ch14-预处理器">Ch14 预处理器</h2>
<h3 id="14-1-预定义符号">14.1 预定义符号</h3>
<table>
<thead>
<tr>
<th>符号</th>
<th>样例</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>_<em>FILE</em>_</td>
<td>“name.c”</td>
<td>进行编译的文件名</td>
</tr>
<tr>
<td>_<em>LINE</em>_</td>
<td>25</td>
<td>文件当前行的行号</td>
</tr>
<tr>
<td>_<em>DATE</em>_</td>
<td>“Jan 31 1997”</td>
<td>文件被编译的日期</td>
</tr>
<tr>
<td>_<em>TIME</em>_</td>
<td>“18:04:30”</td>
<td>文件被编译的时间</td>
</tr>
<tr>
<td>_<em>STDC</em>_</td>
<td>1</td>
<td>如果编译器遵循ANSI C，值为1</td>
</tr>
</tbody>
</table>
<h3 id="14-2-define">14.2 #define</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> name stuff</span></span><br></pre></td></tr></table></figure>
<p>替换文本不仅限于数值字面值常量。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> reg register</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> do_forever for(;;)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CASE break;case</span></span><br></pre></td></tr></table></figure>
<h4 id="14-2-1-宏">14.2.1 宏</h4>
<p>#define允许把参数替换到文本中，如：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SQUARE(x) (x)*(x)</span></span><br><span class="line"></span><br><span class="line">SQUARE(<span class="number">5</span>)   <span class="comment">// 输出25</span></span><br></pre></td></tr></table></figure>
<h4 id="14-2-3-宏与函数">14.2.3 宏与函数</h4>
<p>可以使用宏来实现简单的函数，如比较大小：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX(a, b) ((a)&gt;(b) ? (a) : (b))</span></span><br></pre></td></tr></table></figure>
<h4 id="14-2-6-undef">14.2.6 #undef</h4>
<p>移除一个宏定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">undef</span> name</span></span><br></pre></td></tr></table></figure>
<h3 id="14-3-条件编译">14.3 条件编译</h3>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">if</span> 常量表达式</span></span><br><span class="line">	statements</span><br><span class="line"><span class="meta">#<span class="meta-keyword">elif</span> 常量表达式</span></span><br><span class="line">    statements</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">    statements</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>
<ul>
<li>如果常量表达式非零，则statements正常编译，否则不编译</li>
</ul>

  
  
    
    <div class='footer'>
      
      
      
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2020年11月11日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/c/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>c</p></a></div>


        
      
    </div>
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2020/11/16/learning-notes/Rust-notes/'>
          <p class='title'><i class="fas fa-chevron-left" aria-hidden="true"></i>Rust - Learn</p>
          <p class='content'>Ch0 安装Rust


使用rustup安装
1curl --proto &#x27;=https&#x27; --tlsv1.2 -sSf https://sh.rustup.rs | sh...</p>
        </a>
      
      
        <a class='next' href='/2020/11/04/others/%E5%A4%8D%E4%B9%A0-SQ1%E5%A4%8D%E5%BD%A2/'>
          <p class='title'>复习 - SQ1复形<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>Overview

CS Algs by Depth
Depth 1



Shape
Scramble
Solve





/
/



Depth 2



Shape
Scramble
...</p>
        </a>
      
    </div>
  
</article>


  

  






</div>
<aside class='l_side'>
  
  
    
    



  <section class="widget toc-wrapper shadow floatable desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch2-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5"><span class="toc-text">Ch2 基本概念</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E7%8E%AF%E5%A2%83"><span class="toc-text">2.1 环境</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-1-%E7%BF%BB%E8%AF%91%E7%8E%AF%E5%A2%83"><span class="toc-text">2.1.1 翻译环境</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-4-%E6%89%A7%E8%A1%8C%E7%8E%AF%E5%A2%83"><span class="toc-text">2.1.4 执行环境</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-%E8%AF%8D%E6%B3%95%E8%A7%84%E5%88%99"><span class="toc-text">2.2 词法规则</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-1-%E5%AD%97%E7%AC%A6"><span class="toc-text">2.2.1 字符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-2-%E6%B3%A8%E9%87%8A"><span class="toc-text">2.2.2 注释</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#TIPS"><span class="toc-text">TIPS:</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch3-%E6%95%B0%E6%8D%AE"><span class="toc-text">Ch3 数据</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="toc-text">3.1 基本数据类型</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-1-%E6%95%B4%E5%9E%8B"><span class="toc-text">3.1.1 整型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-2-%E6%B5%AE%E7%82%B9%E7%B1%BB%E5%9E%8B"><span class="toc-text">3.1.2 浮点类型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-3-%E6%8C%87%E9%92%88"><span class="toc-text">3.1.3 指针</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2-%E5%9F%BA%E6%9C%AC%E5%A3%B0%E6%98%8E"><span class="toc-text">3.2 基本声明</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-2-%E5%A3%B0%E6%98%8E%E7%AE%80%E5%8D%95%E6%95%B0%E7%BB%84"><span class="toc-text">3.2.2 声明简单数组</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-3-%E5%A3%B0%E6%98%8E%E6%8C%87%E9%92%88"><span class="toc-text">3.2.3 声明指针</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-typedef"><span class="toc-text">3.3 typedef</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-4-%E5%B8%B8%E9%87%8F"><span class="toc-text">3.4 常量</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-5-%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-text">3.5 作用域</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5-1-%E4%BB%A3%E7%A0%81%E5%9D%97%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-text">3.5.1 代码块作用域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5-2-%E6%96%87%E4%BB%B6%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-text">3.5.2 文件作用域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5-3-%E5%8E%9F%E5%9E%8B%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-text">3.5.3 原型作用域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5-4-%E5%87%BD%E6%95%B0%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="toc-text">3.5.4 函数作用域</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-6-%E9%93%BE%E6%8E%A5%E5%B1%9E%E6%80%A7"><span class="toc-text">3.6 链接属性</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-7-%E5%AD%98%E5%82%A8%E7%B1%BB%E5%9E%8B"><span class="toc-text">3.7 存储类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-8-static%E5%85%B3%E9%94%AE%E5%AD%97"><span class="toc-text">3.8 static关键字</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-9-%E6%80%BB%E7%BB%93"><span class="toc-text">3.9 总结</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch4-%E8%AF%AD%E5%8F%A5"><span class="toc-text">Ch4 语句</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-%E7%A9%BA%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.1 空语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.2 表达式语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-3-%E4%BB%A3%E7%A0%81%E5%9D%97"><span class="toc-text">4.3 代码块</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-4-if%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.4 if语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-5-while%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.5 while语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-6-for%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.6 for语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-7-do%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.7 do语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-8-switch%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.8 switch语句</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-9-goto%E8%AF%AD%E5%8F%A5"><span class="toc-text">4.9 goto语句</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch5-%E6%93%8D%E4%BD%9C%E7%AC%A6%E5%92%8C%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">Ch5 操作符和表达式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-1-%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1 操作符</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-1-%E7%AE%97%E6%9C%AF%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.1 算术操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-2-%E7%A7%BB%E4%BD%8D%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.2 移位操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-3-%E4%BD%8D%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.3 位操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-5-%E5%8D%95%E7%9B%AE%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.5 单目操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-6-%E5%85%B3%E7%B3%BB%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.6 关系操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-7-%E9%80%BB%E8%BE%91%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.7 逻辑操作符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-1-8-%E6%9D%A1%E4%BB%B6%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-text">5.1.8 条件操作符</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-2-%E5%B8%83%E5%B0%94%E5%80%BC"><span class="toc-text">5.2 布尔值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-4-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BC"><span class="toc-text">5.4 表达式求值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch6-%E6%8C%87%E9%92%88"><span class="toc-text">Ch6 指针</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#6-1-%E5%86%85%E5%AD%98%E5%92%8C%E5%9C%B0%E5%9D%80"><span class="toc-text">6.1 内存和地址</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-2-%E5%80%BC%E5%92%8C%E7%B1%BB%E5%9E%8B"><span class="toc-text">6.2 值和类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-5-%E6%9C%AA%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E9%9D%9E%E6%B3%95%E7%9A%84%E6%8C%87%E9%92%88"><span class="toc-text">6.5 未初始化和非法的指针</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-6-NULL%E6%8C%87%E9%92%88"><span class="toc-text">6.6 NULL指针</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-7-%E6%8C%87%E9%92%88%E3%80%81%E9%97%B4%E6%8E%A5%E8%AE%BF%E9%97%AE%E5%92%8C%E5%B7%A6%E5%80%BC"><span class="toc-text">6.7 指针、间接访问和左值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-10-%E6%8C%87%E9%92%88%E7%9A%84%E6%8C%87%E9%92%88"><span class="toc-text">6.10 指针的指针</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-11-%E6%8C%87%E9%92%88%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">6.11 指针表达式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-13-%E6%8C%87%E9%92%88%E8%BF%90%E7%AE%97"><span class="toc-text">6.13 指针运算</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#6-13-1-%E7%AE%97%E6%9C%AF%E8%BF%90%E7%AE%97"><span class="toc-text">6.13.1 算术运算</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-13-2-%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97"><span class="toc-text">6.13.2 关系运算</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch7-%E5%87%BD%E6%95%B0"><span class="toc-text">Ch7 函数</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#7-2-%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E"><span class="toc-text">7.2 函数声明</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#7-2-1-%E5%8E%9F%E5%9E%8B"><span class="toc-text">7.2.1 原型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-2-2-%E5%87%BD%E6%95%B0%E7%9A%84%E7%BC%BA%E7%9C%81%E8%AE%A4%E5%AE%9A"><span class="toc-text">7.2.2 函数的缺省认定</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-3-%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0"><span class="toc-text">7.3 函数的参数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-4-ADT%E5%92%8C%E9%BB%91%E7%9B%92"><span class="toc-text">7.4 ADT和黑盒</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-5-%E9%80%92%E5%BD%92"><span class="toc-text">7.5 递归</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#7-5-1-%E8%BF%BD%E8%B8%AA%E9%80%92%E5%BD%92%E5%87%BD%E6%95%B0"><span class="toc-text">7.5.1 追踪递归函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-5-2-%E9%80%92%E5%BD%92%E4%B8%8E%E8%BF%AD%E4%BB%A3"><span class="toc-text">7.5.2 递归与迭代</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-6-%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8"><span class="toc-text">7.6 可变参数列表</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#7-6-1-stdarg%E5%AE%8F"><span class="toc-text">7.6.1 stdarg宏</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-6-2-%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%99%90%E5%88%B6"><span class="toc-text">7.6.2 可变参数的限制</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch8-%E6%95%B0%E7%BB%84"><span class="toc-text">Ch8 数组</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#8-1-%E4%B8%80%E7%BB%B4%E6%95%B0%E7%BB%84"><span class="toc-text">8.1 一维数组</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-1-%E6%95%B0%E7%BB%84%E5%90%8D"><span class="toc-text">8.1.1 数组名</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-3-%E6%8C%87%E9%92%88%E4%B8%8E%E4%B8%8B%E6%A0%87"><span class="toc-text">8.1.3 指针与下标</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-5-%E6%95%B0%E7%BB%84%E5%92%8C%E6%8C%87%E9%92%88"><span class="toc-text">8.1.5 数组和指针</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-7-%E5%A3%B0%E6%98%8E%E6%95%B0%E7%BB%84%E5%8F%82%E6%95%B0"><span class="toc-text">8.1.7 声明数组参数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-8-%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-text">8.1.8 初始化</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-9-%E4%B8%8D%E5%AE%8C%E6%95%B4%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-text">8.1.9 不完整的初始化</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-10-%E8%87%AA%E5%8A%A8%E8%AE%A1%E7%AE%97%E6%95%B0%E7%BB%84%E9%95%BF%E5%BA%A6"><span class="toc-text">8.1.10 自动计算数组长度</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-1-11-%E5%AD%97%E7%AC%A6%E6%95%B0%E7%BB%84%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-text">8.1.11 字符数组的初始化</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-2-%E5%A4%9A%E7%BB%B4%E6%95%B0%E7%BB%84"><span class="toc-text">8.2 多维数组</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-1-%E5%AD%98%E5%82%A8%E9%A1%BA%E5%BA%8F"><span class="toc-text">8.2.1 存储顺序</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-2-%E6%95%B0%E7%BB%84%E5%90%8D"><span class="toc-text">8.2.2 数组名</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-4-%E6%8C%87%E5%90%91%E6%95%B0%E7%BB%84%E7%9A%84%E6%8C%87%E9%92%88"><span class="toc-text">8.2.4 指向数组的指针</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-5-%E4%BD%9C%E4%B8%BA%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E7%9A%84%E5%A4%9A%E7%BB%B4%E6%95%B0%E7%BB%84"><span class="toc-text">8.2.5 作为函数参数的多维数组</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-6-%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-text">8.2.6 初始化</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-2-7-%E6%95%B0%E7%BB%84%E9%95%BF%E5%BA%A6%E8%87%AA%E5%8A%A8%E8%AE%A1%E7%AE%97"><span class="toc-text">8.2.7 数组长度自动计算</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-3-%E6%8C%87%E9%92%88%E6%95%B0%E7%BB%84"><span class="toc-text">8.3 指针数组</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch9-%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%81%E5%AD%97%E7%AC%A6%E5%92%8C%E5%AD%97%E8%8A%82"><span class="toc-text">Ch9 字符串、字符和字节</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#9-1-%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%9F%BA%E7%A1%80"><span class="toc-text">9.1 字符串基础</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-2-%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%95%BF%E5%BA%A6"><span class="toc-text">9.2 字符串长度</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-3-%E4%B8%8D%E5%8F%97%E9%99%90%E5%88%B6%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0"><span class="toc-text">9.3 不受限制的字符串函数</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#9-3-1-%E5%A4%8D%E5%88%B6%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-text">9.3.1 复制字符串</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-3-2-%E8%BF%9E%E6%8E%A5%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-text">9.3.2 连接字符串</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-3-4-%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%AF%94%E8%BE%83"><span class="toc-text">9.3.4 字符串比较</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-4-%E9%95%BF%E5%BA%A6%E5%8F%97%E9%99%90%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0"><span class="toc-text">9.4 长度受限的字符串函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-5-%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9F%A5%E6%89%BE%E5%9F%BA%E7%A1%80"><span class="toc-text">9.5 字符串查找基础</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#9-5-1-%E6%9F%A5%E6%89%BE%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6"><span class="toc-text">9.5.1 查找一个字符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-5-2-%E6%9F%A5%E6%89%BE%E4%BB%BB%E4%BD%95%E5%87%A0%E4%B8%AA%E5%AD%97%E7%AC%A6"><span class="toc-text">9.5.2 查找任何几个字符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-5-3-%E6%9F%A5%E6%89%BE%E4%B8%80%E4%B8%AA%E5%AD%90%E4%B8%B2"><span class="toc-text">9.5.3 查找一个子串</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-6-%E9%AB%98%E7%BA%A7%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9F%A5%E6%89%BE"><span class="toc-text">9.6 高级字符串查找</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#9-6-1-%E6%9F%A5%E6%89%BE%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%89%8D%E7%BC%80"><span class="toc-text">9.6.1 查找一个字符串前缀</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-6-2-%E6%9F%A5%E6%89%BE%E6%A0%87%E8%AE%B0"><span class="toc-text">9.6.2 查找标记</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-7-%E9%94%99%E8%AF%AF%E4%BF%A1%E6%81%AF"><span class="toc-text">9.7 错误信息</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-8-%E5%AD%97%E7%AC%A6%E6%93%8D%E4%BD%9C"><span class="toc-text">9.8 字符操作</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#9-8-1-%E5%AD%97%E7%AC%A6%E5%88%86%E7%B1%BB"><span class="toc-text">9.8.1 字符分类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-8-2-%E5%AD%97%E7%AC%A6%E5%A4%A7%E5%B0%8F%E5%86%99%E8%BD%AC%E6%8D%A2"><span class="toc-text">9.8.2 字符大小写转换</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-9-%E5%86%85%E5%AD%98%E6%93%8D%E4%BD%9C"><span class="toc-text">9.9 内存操作</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch10-%E7%BB%93%E6%9E%84%E5%92%8C%E8%81%94%E5%90%88"><span class="toc-text">Ch10 结构和联合</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#10-1-%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86"><span class="toc-text">10.1 结构基础知识</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#10-1-1-%E7%BB%93%E6%9E%84%E5%A3%B0%E6%98%8E"><span class="toc-text">10.1.1 结构声明</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-1-2-%E7%BB%93%E6%9E%84%E6%88%90%E5%91%98"><span class="toc-text">10.1.2 结构成员</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-1-5-%E7%BB%93%E6%9E%84%E7%9A%84%E8%87%AA%E5%BC%95%E7%94%A8"><span class="toc-text">10.1.5 结构的自引用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-1-6-%E4%B8%8D%E5%AE%8C%E6%95%B4%E7%9A%84%E5%A3%B0%E6%98%8E"><span class="toc-text">10.1.6 不完整的声明</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-2-%E7%BB%93%E6%9E%84%E3%80%81%E6%8C%87%E9%92%88%E5%92%8C%E6%88%90%E5%91%98"><span class="toc-text">10.2 结构、指针和成员</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#10-2-1-%E8%AE%BF%E9%97%AE%E6%8C%87%E9%92%88"><span class="toc-text">10.2.1 访问指针</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-2-2-%E8%AE%BF%E9%97%AE%E7%BB%93%E6%9E%84"><span class="toc-text">10.2.2 访问结构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#image-2020110118534746710-2-3-%E8%AE%BF%E9%97%AE%E7%BB%93%E6%9E%84%E6%88%90%E5%91%98"><span class="toc-text">10.2.3 访问结构成员</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-2-4-%E8%AE%BF%E9%97%AE%E5%B5%8C%E5%A5%97%E7%9A%84%E7%BB%93%E6%9E%84"><span class="toc-text">10.2.4 访问嵌套的结构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-2-5-%E8%AE%BF%E9%97%AE%E6%8C%87%E9%92%88%E6%88%90%E5%91%98"><span class="toc-text">10.2.5 访问指针成员</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-3-%E7%BB%93%E6%9E%84%E7%9A%84%E5%AD%98%E5%82%A8%E5%88%86%E9%85%8D"><span class="toc-text">10.3 结构的存储分配</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-4-%E4%BD%9C%E4%B8%BA%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E7%9A%84%E7%BB%93%E6%9E%84"><span class="toc-text">10.4 作为函数参数的结构</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-5-%E4%BD%8D%E6%AE%B5"><span class="toc-text">10.5 位段</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-6-%E8%81%94%E5%90%88"><span class="toc-text">10.6 联合</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch11-%E5%8A%A8%E6%80%81%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"><span class="toc-text">Ch11 动态内存分配</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#11-1-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E5%88%86%E9%85%8D%E5%86%85%E5%AD%98"><span class="toc-text">11.1 为什么使用动态分配内存</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#11-2-malloc%E5%92%8Cfree"><span class="toc-text">11.2 malloc和free</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#11-2-1-malloc"><span class="toc-text">11.2.1 malloc</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#11-2-2-free"><span class="toc-text">11.2.2 free</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#11-3-calloc%E5%92%8Crealloc"><span class="toc-text">11.3 calloc和realloc</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#11-3-1-calloc"><span class="toc-text">11.3.1 calloc</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#11-3-2-realloc"><span class="toc-text">11.3.2 realloc</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#11-4-%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E5%88%86%E9%85%8D%E7%9A%84%E5%86%85%E5%AD%98"><span class="toc-text">11.4 使用动态分配的内存</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#11-5-%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8A%A8%E6%80%81%E5%86%85%E5%AD%98%E9%94%99%E8%AF%AF"><span class="toc-text">11.5 常见的动态内存错误</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch12-%E4%BD%BF%E7%94%A8%E7%BB%93%E6%9E%84%E5%92%8C%E6%8C%87%E9%92%88"><span class="toc-text">Ch12 使用结构和指针</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#12-2-%E5%8D%95%E9%93%BE%E8%A1%A8"><span class="toc-text">12.2 单链表</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#12-2-1-%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E6%9C%89%E5%BA%8F%E5%8D%95%E9%93%BE%E8%A1%A8"><span class="toc-text">12.2.1 插入一个有序单链表</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#12-3-%E5%8F%8C%E9%93%BE%E8%A1%A8"><span class="toc-text">12.3 双链表</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Ch14-%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8"><span class="toc-text">Ch14 预处理器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#14-1-%E9%A2%84%E5%AE%9A%E4%B9%89%E7%AC%A6%E5%8F%B7"><span class="toc-text">14.1 预定义符号</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-2-define"><span class="toc-text">14.2 #define</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#14-2-1-%E5%AE%8F"><span class="toc-text">14.2.1 宏</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#14-2-3-%E5%AE%8F%E4%B8%8E%E5%87%BD%E6%95%B0"><span class="toc-text">14.2.3 宏与函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#14-2-6-undef"><span class="toc-text">14.2.6 #undef</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-3-%E6%9D%A1%E4%BB%B6%E7%BC%96%E8%AF%91"><span class="toc-text">14.3 条件编译</span></a></li></ol></li></ol>
    </div>
  </section>


  


</aside>



        
        
          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<script>
  window.pdata={}
  pdata.ispage=true;
  pdata.postTitle="Pointers on C - Learn";
  pdata.commentPath="";
  pdata.commentPlaceholder="";

  var l_header=document.getElementById("l_header");
  
  l_header.classList.add("show");
  
</script>

        
      </div>
      
  
  <footer class="footer clearfix">
    <br><br>
    
      
        <div class='copyright'>
        <p><a target="_blank" rel="noopener" href="https://github.com/Schenk75/Schenk75.github.io">Copyright © 2020-2022 Schenk</a></p>

        </div>
      
    
  </footer>


      <a id="s-top" class="fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
    </div>
  </div>
  <div>
    <script>
window.volantis={};
window.volantis.loadcss=document.getElementById("loadcss");
/********************脚本懒加载函数********************************/
function loadScript(src, cb) {
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
if (cb) script.onload = cb;
script.setAttribute('src', src);
HEAD.appendChild(script);
}
//https://github.com/filamentgroup/loadCSS
var loadCSS = function( href, before, media, attributes ){
	var doc = window.document;
	var ss = doc.createElement( "link" );
	var ref;
	if( before ){
		ref = before;
	}
	else {
		var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
		ref = refs[ refs.length - 1];
	}
	var sheets = doc.styleSheets;
	if( attributes ){
		for( var attributeName in attributes ){
			if( attributes.hasOwnProperty( attributeName ) ){
				ss.setAttribute( attributeName, attributes[attributeName] );
			}
		}
	}
	ss.rel = "stylesheet";
	ss.href = href;
	ss.media = "only x";
	function ready( cb ){
		if( doc.body ){
			return cb();
		}
		setTimeout(function(){
			ready( cb );
		});
	}
	ready( function(){
		ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
	});
	var onloadcssdefined = function( cb ){
		var resolvedHref = ss.href;
		var i = sheets.length;
		while( i-- ){
			if( sheets[ i ].href === resolvedHref ){
				return cb();
			}
		}
		setTimeout(function() {
			onloadcssdefined( cb );
		});
	};
	function loadCB(){
		if( ss.addEventListener ){
			ss.removeEventListener( "load", loadCB );
		}
		ss.media = media || "all";
	}
	if( ss.addEventListener ){
		ss.addEventListener( "load", loadCB);
	}
	ss.onloadcssdefined = onloadcssdefined;
	onloadcssdefined( loadCB );
	return ss;
};
</script>
<script>
  
  loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css", window.volantis.loadcss);
  
  
  
  
</script>
<!-- required -->

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script>

<script>
  function pjax_fancybox() {
    $(".md .gallery").find("img").each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("class", "fancybox");
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 判断当前页面是否存在描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".md .gallery").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  function SCload_fancybox() {
    if ($(".md .gallery").find("img").length == 0) return;
    loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css", document.getElementById("loadcss"));
    setTimeout(function() {
      loadScript('https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js', pjax_fancybox)
    }, 1);
  };
  $(function () {
    SCload_fancybox();
  });
</script>


<!-- internal -->







  <script defer src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  
  
    <script>
      window.FPConfig = {
        delay: 0,
        ignoreKeywords: [],
        maxRPS: 5,
        hoverDelay: 25
      };
    </script>
    <script defer src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script>
  




  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
    var clipboard = new ClipboardJS('.btn-copy', {
        target: function (trigger) {
            return trigger.nextElementSibling
        }
    });
    function wait(callback, seconds) {
        var timelag = null;
        timelag = window.setTimeout(callback, seconds)
    }
    function pjax_initCopyCode() {
		if($(".highlight .code pre").length+$(".article pre code").length==0)return;
        var copyHtml = '';
        copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
        copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
        copyHtml += '</button>';
        $(".highlight .code pre").before(copyHtml);
        $(".article pre code").before(copyHtml);
        clipboard.off('success').on('success', function (e) {
            let $btn = $(e.trigger);
            $btn.addClass('copied');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-check-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPIED';
            wait(function () {
                $icon.removeClass('fa-check-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        });
        clipboard.off('error').on('error', function (e) {
            e.clearSelection();
            let $btn = $(e.trigger);
            $btn.addClass('copy-failed');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-times-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPY FAILED';
            wait(function () {
                $icon.removeClass('fa-times-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        })
    }
    $(function () {
        pjax_initCopyCode()
    });
</script>










  <script defer src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/tools/busuanzi.pure.mini.js" data-pjax></script>


  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/app.min.js"></script>




  
  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/search.min.js"></script>

  


<!-- optional -->

  <script>
const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/";
const ROOT =  ("/" || "/").endsWith('/') ? ("/" || "/") : ("//" || "/" );
function listenSearch(){
  
    customSearch = new HexoSearch({
      imagePath: SearchServiceimagePath
    });
  
}
document.addEventListener("DOMContentLoaded", listenSearch);

</script>











  <script defer>

  const LCCounter = {
    app_id: 'u9j57bwJod4EDmXWdxrwuqQT-MdYXbMMI',
    app_key: 'jfHtEKVE24j0IVCGHbvuFClp',
    custom_api_server: '',

    // 查询存储的记录
    getRecord(Counter, url, title) {
      return new Promise(function (resolve, reject) {
        Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({url})))
          .then(resp => resp.json())
          .then(({results, code, error}) => {
            if (code === 401) {
              throw error;
            }
            if (results && results.length > 0) {
              var record = results[0];
              resolve(record);
            } else {
              Counter('post', '/classes/Counter', {url, title: title, times: 0})
                .then(resp => resp.json())
                .then((record, error) => {
                  if (error) {
                    throw error;
                  }
                  resolve(record);
                }).catch(error => {
                console.error('Failed to create', error);
                reject(error);
              });
            }
          }).catch((error) => {
          console.error('LeanCloud Counter Error:', error);
          reject(error);
        });
      })
    },

    // 发起自增请求
    increment(Counter, incrArr) {
      return new Promise(function (resolve, reject) {
        Counter('post', '/batch', {
          "requests": incrArr
        }).then((res) => {
          res = res.json();
          if (res.error) {
            throw res.error;
          }
          resolve(res);
        }).catch((error) => {
          console.error('Failed to save visitor count', error);
          reject(error);
        });
      });
    },

    // 构建自增请求体
    buildIncrement(objectId) {
      return {
        "method": "PUT",
        "path": `/1.1/classes/Counter/${ objectId }`,
        "body": {
          "times": {
            '__op': 'Increment',
            'amount': 1
          }
        }
      }
    },

    // 校验是否为有效的 UV
    validUV() {
      var key = 'LeanCloudUVTimestamp';
      var flag = localStorage.getItem(key);
      if (flag) {
        // 距离标记小于 24 小时则不计为 UV
        if (new Date().getTime() - parseInt(flag) <= 86400000) {
          return false;
        }
      }
      localStorage.setItem(key, new Date().getTime().toString());
      return true;
    },

    addCount(Counter) {
      var enableIncr = '' === 'true' && window.location.hostname !== 'localhost';
      enableIncr = true;
      var getterArr = [];
      var incrArr = [];
      // 请求 PV 并自增
      var pvCtn = document.querySelector('#lc-sv');
      if (pvCtn || enableIncr) {
        var pvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-sv', 'Visits').then((record) => {
          incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-sv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + 1;
              if (pvCtn) {
                pvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(pvGetter);
      }

      // 请求 UV 并自增
      var uvCtn = document.querySelector('#lc-uv');
      if (uvCtn || enableIncr) {
        var uvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-uv', 'Visitors').then((record) => {
          var vuv = this.validUV();
          vuv && incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-uv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + (vuv ? 1 : 0);
              if (uvCtn) {
                uvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(uvGetter);
      }

      // 请求文章的浏览数，如果是当前页面就自增
      var allPV = document.querySelectorAll('#lc-pv');
      if (allPV.length > 0 || enableIncr) {
        for (i = 0; i < allPV.length; i++) {
          let pv = allPV[i];
          let title = pv.getAttribute('data-title');
          var url = 'http://example.com' + pv.getAttribute('data-path');
          if (url) {
            var viewGetter = this.getRecord(Counter, url, title).then((record) => {
              // 是当前页面就自增
              let curPath = window.location.pathname;
              if (curPath.includes('index.html')) {
                curPath = curPath.substring(0, curPath.lastIndexOf('index.html'));
              }
              if (pv.getAttribute('data-path') == curPath) {
                incrArr.push(this.buildIncrement(record.objectId));
              }
              if (pv) {
                var ele = pv.querySelector('#lc-pv #number');
                if (ele) {
                  if (pv.getAttribute('data-path') == curPath) {
                    ele.innerText = (record.times || 0) + 1;
                  } else {
                    ele.innerText = record.times || 0;
                  }
                  pv.style.display = 'inline';
                }
              }
            });
            getterArr.push(viewGetter);
          }
        }
      }

      // 如果启动计数自增，批量发起自增请求
      if (enableIncr) {
        Promise.all(getterArr).then(() => {
          incrArr.length > 0 && this.increment(Counter, incrArr);
        })
      }

    },


    fetchData(api_server) {
      var Counter = (method, url, data) => {
        return fetch(`${ api_server }/1.1${ url }`, {
          method,
          headers: {
            'X-LC-Id': this.app_id,
            'X-LC-Key': this.app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      this.addCount(Counter);
    },

    refreshCounter() {
      var api_server = this.app_id.slice(-9) !== '-MdYXbMMI' ? this.custom_api_server : `https://${ this.app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
      if (api_server) {
        this.fetchData(api_server);
      } else {
        fetch('https://app-router.leancloud.cn/2/route?appId=' + this.app_id)
          .then(resp => resp.json())
          .then(({api_server}) => {
            this.fetchData('https://' + api_server);
          });
      }
    }

  };

  LCCounter.refreshCounter();

  document.addEventListener('pjax:complete', function () {
    LCCounter.refreshCounter();
  });
</script>








<script>
function listennSidebarTOC() {
  const navItems = document.querySelectorAll(".toc li");
  if (!navItems.length) return;
  const sections = [...navItems].map((element) => {
    const link = element.querySelector(".toc-link");
    const target = document.getElementById(
      decodeURI(link.getAttribute("href")).replace("#", "")
    );
    link.addEventListener("click", (event) => {
      event.preventDefault();
      window.scrollTo({
		top: target.offsetTop + 100,
		
		behavior: "smooth"
		
	  });
    });
    return target;
  });

  function activateNavByIndex(target) {
    if (target.classList.contains("active-current")) return;

    document.querySelectorAll(".toc .active").forEach((element) => {
      element.classList.remove("active", "active-current");
    });
    target.classList.add("active", "active-current");
    let parent = target.parentNode;
    while (!parent.matches(".toc")) {
      if (parent.matches("li")) parent.classList.add("active");
      parent = parent.parentNode;
    }
  }

  function findIndex(entries) {
    let index = 0;
    let entry = entries[index];
    if (entry.boundingClientRect.top > 0) {
      index = sections.indexOf(entry.target);
      return index === 0 ? 0 : index - 1;
    }
    for (; index < entries.length; index++) {
      if (entries[index].boundingClientRect.top <= 0) {
        entry = entries[index];
      } else {
        return sections.indexOf(entry.target);
      }
    }
    return sections.indexOf(entry.target);
  }

  function createIntersectionObserver(marginTop) {
    marginTop = Math.floor(marginTop + 10000);
    let intersectionObserver = new IntersectionObserver(
      (entries, observe) => {
        let scrollHeight = document.documentElement.scrollHeight + 100;
        if (scrollHeight > marginTop) {
          observe.disconnect();
          createIntersectionObserver(scrollHeight);
          return;
        }
        let index = findIndex(entries);
        activateNavByIndex(navItems[index]);
      },
      {
        rootMargin: marginTop + "px 0px -100% 0px",
        threshold: 0,
      }
    );
    sections.forEach((element) => {
      element && intersectionObserver.observe(element);
    });
  }
  createIntersectionObserver(document.documentElement.scrollHeight);
}

document.addEventListener("DOMContentLoaded", listennSidebarTOC);
document.addEventListener("pjax:success", listennSidebarTOC);
</script>

<!-- more -->




    
      


<script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',
        selectors: [
          "title",
          "#l_cover",
          "#pjax-container",
          "#pjax-header-nav-list"
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      window.subData = null; // 移除标题（用于一二级导航栏切换处）
      if (typeof $.fancybox != "undefined") {
        $.fancybox.close();    // 关闭弹窗
      }
      volantis.$switcher.removeClass('active'); // 关闭移动端激活的搜索框
      volantis.$header.removeClass('z_search-open'); // 关闭移动端激活的搜索框
      volantis.$wrapper.removeClass('sub'); // 跳转页面时关闭二级导航

      // 解绑事件 避免重复监听
      volantis.$topBtn.unbind('click');
      $('.menu a').unbind('click');
      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');
	  
    });

    document.addEventListener('pjax:complete', function () {
      // 关于百度统计对 SPA 页面的处理：
      // 方案一：百度统计>管理>单页应用设置中，打开开启按钮即可对SPA进行统计。 https://tongji.baidu.com/web/help/article?id=324
      // 方案二：取消注释下列代码。 https://tongji.baidu.com/web/help/article?id=235
      // 

      // 关于谷歌统计对 SPA 页面的处理：
      // 当应用以动态方式加载内容并更新地址栏中的网址时，也应该更新通过 gtag.js 存储的网页网址。
      // https://developers.google.cn/analytics/devguides/collection/gtagjs/single-page-applications?hl=zh-cn
      

      $('.nav-main').find('.list-v').not('.menu-phone').removeAttr("style",""); // 移除小尾巴的移除
      $('.menu-phone.list-v').removeAttr("style",""); // 移除小尾巴的移除
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
      try{
          if (typeof $.fancybox == "undefined") {
            SCload_fancybox();
          } else {
            pjax_fancybox();
          }
        
        
        
        
        
          pjax_initCopyCode();
        
        
        
        
        
      } catch (e) {
        console.log(e);
      }
	  
    });

    document.addEventListener('pjax:error', function (e) {
	  
      window.location.href = e.triggerElement.href;
    });
</script>

    
  </div>
</body>
</html>
